import dayjs from 'dayjs';
import { formatOptions, colorToRgba, legendStyle, xLabelStyle, yLabelStyle } from './formatter';
import type { Options, XType, YType, BaseNameDataObject } from './type';
import { getMaxAndMin, formatDecimal } from './util';

interface YData extends BaseNameDataObject {
  tooltipTitles?: string[];
}

interface LineChartProps {
  selected: any;
  grid?: any;
  legend?: any;
  tooltip?: Function;
  options: Options;
  xType: XType;
  yType: YType;
  xData: number[] | string[];
  yData: YData[];
}

const DEBUG = false;

export const createLineOption = ({ selected, grid, legend, tooltip, options, xType, yType, xData, yData }: LineChartProps) => {
  // 格式化options
  options = formatOptions(options);

  // 设定距离
  const { maxValue, minValue } = getMaxAndMin(yData);
  // if (yType === "number") {
  //   options.distance = getDistance(maxValue, minValue);
  // } else {
  //   options.distance = 36;
  // }

  // 图表边界
  // 暂时封存
  // const defaultGrid = {
  //   left: 10 - options.distance, // 组件离容器左侧的距离
  //   right: 20, // 组件离容器右侧的距离(最后一个x轴标签漏出一半的宽度为20)
  //   top: 10, // 组件离容器上侧的距离(最后一个y轴标签漏出一半的高度为10)
  //   bottom: 0, // 组件离容器下侧的距离
  //   containLabel: true, // grid区域是否包含坐标轴的刻度标签
  // };
  const defaultGrid = {
    left: 40, // 组件离容器左侧的距离
    right: 20, // 组件离容器右侧的距离
    top: 10, // 组件离容器上侧的距离(无图例10，图例在上时30/-4，显示y轴名称时45)
    bottom: 25, // 组件离容器下侧的距离(无图例25，图例在下时50/-5；不显示x轴标签时10)
    containLabel: false // grid区域是否包含坐标轴的刻度标签
  };
  let finalGrid = defaultGrid;
  if (grid) {
    finalGrid = Object.assign(defaultGrid, grid);
  }

  // 图例
  const defaultLegend = {
    show: yData.length > 1 && options.showLegend,
    // icon: "rect", // 图例图标形状
    icon: 'path://M0 1a1 1 0 0 1 1 -1h18a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-18a1 1 0 0 1 -1 -1z', // svg转path
    borderWidth: DEBUG ? 1 : 0,
    borderColor: DEBUG ? 'red' : 'transparent',
    // height: 20,
    itemWidth: 20, // 图例图标宽度
    itemHeight: 6, // 图例图标高度
    itemGap: 26, // 图例每项之间的间隔
    padding: [0, 0, 0, 0], // 图例内边距，单位px，默认上下左右内边距为5
    // borderRadius: 1,
    // top: 0,
    // right: 2,
    textStyle: legendStyle(), // 图例文本
    data: yData.map((item) => item.name), // 图例名称，要与series.name对应
    selected // 图例选择状态
  };
  let finalLegend = defaultLegend;
  if (legend) {
    finalLegend = Object.assign(defaultLegend, legend);
  }

  /**
   * 针对不同配置调整图表边界与图例位置
   */
  // 包含多条折线的情况，默认认为一定要显示图例
  if (yData.length > 1) {
    if (options.legendPosition === 'top') {
      finalGrid.top = 38;
      (finalLegend as any).top = 0;
    } else if (options.legendPosition === 'bottom') {
      finalGrid.bottom = 38;
      (finalLegend as any).bottom = 2;
    }
  }
  // 显示y轴名称的情况
  if (options.showSeriesName) {
    finalGrid.top = 38;
  }
  // 暂不考虑有图例的时候，又不显示x轴标签的情况，只考虑没有图例即单条折线的情况
  if (yData.length === 1 && !options.showLabel) {
    finalGrid.bottom = 10;
    finalGrid.right = 0;
  }

  /**
   * 图表配置主体
   */
  const ret = {
    grid: finalGrid,
    legend: finalLegend,
    tooltip: {
      trigger: 'axis', // 坐标轴触发，折线图等会使用类目轴的图表中使用
      showDelay: 0, // 显示延迟，添加显示延迟可以避免频繁切换，单位ms
      backgroundColor: 'rgba(0, 0, 0, 0.6)', // 背景颜色
      padding: 8,
      borderRadius: 6, // 边框圆角
      borderWidth: 0, // 边框宽度
      formatter: tooltip
        ? tooltip
        : (params: any) => {
          // 副标题
          let subTitle = params[0].axisValue;
          if (xType === 'date') {
            subTitle = dayjs.unix(params[0].axisValue).format('MM/DD');
          } else if (xType === 'time') {
            subTitle = dayjs.unix(params[0].axisValue).format('MM/DD HH:mm');
          }
          const subTitleStr = `<div class="subtitle">${subTitle}</div>`;

          // 标题
          let titleStr = '';
          params.forEach((item: any) => {
            const series = yData[item.seriesIndex];
            const titles = series.tooltipTitles;
            if (titles?.length) {
              const title = titles[item.dataIndex];
              titleStr = `<div class="title">${title}</div>`;
            }
          });

          // 图例数据
          let itemStr = '';
          params.forEach((item: any) => {
            let number = item.value;
            let unit = '';
            if (yType === 'percent') {
              // number = (number * 100).toFixed(2);
              number = formatDecimal(number, options.percentPrecision as number);
              unit = '%';
            } else if (yType === 'number') {
              // if (number > 10000) {
              //   number = parseFloat((number / 10000).toFixed(1));
              //   unit = "万";
              // }
            }

            itemStr += `<div class="row">
                <div class="sample" style="background: ${item.color}"></div>
                <div class="name">${item.seriesName}：</div>
                <div class="value">
                  <div class="value-inner">
                    <span class="unit">${unit}</span>
                    <span class="number">${typeof item.data === 'object' ? item.data?.displayValue : number.toLocaleString()}</span>
                  </div>
                </div>
              </div>`;
          });

          const str = `<div class="chart-tooltip line">
              ${titleStr}
              ${subTitleStr}
              ${itemStr}
            </div>`;

          return str;
        },
      axisPointer: {
        z: 0,
        lineStyle: {
          type: 'dashed',
          width: 2,
          color: '#92ACF2'
        }
      } // 坐标轴指示器配置项，默认不显示，tooltip.trigger 设置为 'axis' 时会显示
    },
    color: yData.map((item) => item.color),
    xAxis: {
      type: 'category',
      triggerEvent: false, // 是否触发事件
      boundaryGap: false, // x坐标轴两边是否留白，不留白时，第一个和最后一个数据点会被遮挡
      axisLine: {
        show: true,
        lineStyle: {
          color: '#E5E6EC',
          type: 'solid'
        }
      }, // 坐标轴线
      axisTick: {
        show: false
      }, // 坐标轴刻度
      axisLabel: xLabelStyle(xType, options), // 坐标轴标签
      data: xData
    },
    yAxis: {
      type: 'value',
      name: options.showSeriesName ? options.seriesName || yData[0]?.name : '',
      nameLocation: 'end',
      nameTextStyle: {
        align: 'left',
        color: '#8F98B2',
        // padding: [0, 0, 3, 0 - options.distance],
        padding: [0, 0, 3, -40],
        fontSize: 12,
        lineHeight: 20,
        fontFamily: 'PingFang SC, sans-serif'
      },
      axisLabel: yLabelStyle(yType, options), // 坐标轴标签
      splitLine: {
        show: true,
        lineStyle: {
          color: '#E5E6EC',
          type: 'dashed'
        }
      } // 分割线
    },
    series: yData.map((item, index) => {
      return {
        type: 'line',
        data: item.data,
        name: item.name,
        yAxisIndex: 0,
        zlevel: yData.length - index, // 图层顺序
        lineStyle: {
          color: item.color
        },
        areaStyle: {
          color: {
            type: 'linear',
            x: 0,
            y: 0,
            x2: 0,
            y2: 1,
            colorStops: [
              {
                offset: 0,
                color: colorToRgba(item.color, 0.16)
              },
              {
                offset: 1,
                color: colorToRgba(item.color, 0)
              }
            ]
          }
        },
        showSymbol: false,
        symbolSize: 10,
        markLine: options.showMarkLine ? options.markLine ?? {
          data: [{ /* yAxis: 0, */ type: 'average', name: '平均值' }],
          symbol: ['none', 'none'],
          label: {
            color: '#999999',
            padding: [0, 0, 0, -50],
            position: 'insideEndTop'
            // https://echarts.apache.org/zh/option.html#series-line.markLine.label.formatter
            /* formatter(params) {
              // console.log('params', params);
            } */
          },
          lineStyle: {
            color: '#999999'
          },
          animationDuration: 300
        } : false
      };
    })
  };

  /**
   * 针对特殊数量集的特殊处理
   */
  // 处理y轴为数字的情况
  if (yType === 'number') {
    let min: number | null = null;
    let max: number | null = null;
    let interval: number | null = null;

    if (yData?.length === 1) {
      /**
       * 操作1: 处理数据量级很大的情况(多条线的情况不执行此逻辑，因为会导致y轴跨度写死)
       */
      if (maxValue !== minValue) {
        const diff = maxValue - minValue;
        if (diff <= 100) {
          const res0 = getOptions(maxValue, minValue, 0);
          min = res0.min;
          max = res0.max;
          interval = res0.interval;

          const res10 = getOptions(maxValue, minValue, 1);
          min = res10.min;
          max = res10.max;
          interval = res10.interval;
        }

        if (diff > 100 && diff <= 10000) {
          const res0 = getOptions(maxValue, minValue, 0);
          min = res0.min;
          max = res0.max;
          interval = res0.interval;

          const res10 = getOptions(maxValue, minValue, 1);
          min = res10.min;
          max = res10.max;
          interval = res10.interval;

          const res100 = getOptions(maxValue, minValue, 2);
          min = res100.min;
          max = res100.max;
          interval = res100.interval;

          const res1000 = getOptions(maxValue, minValue, 3);
          min = res1000.min;
          max = res1000.max;
          interval = res1000.interval;
        }

        if (diff > 10000) {
          const res0 = getOptions(maxValue, minValue, 0);
          min = res0.min;
          max = res0.max;
          interval = res0.interval;

          const res10 = getOptions(maxValue, minValue, 1);
          min = res10.min;
          max = res10.max;
          interval = res10.interval;

          const res100 = getOptions(maxValue, minValue, 2);
          min = res100.min;
          max = res100.max;
          interval = res100.interval;

          const res1000 = getOptions(maxValue, minValue, 3);
          min = res1000.min;
          max = res1000.max;
          interval = res1000.interval;

          const res10000 = getOptions(maxValue, minValue, 4);
          min = res10000.min;
          max = res10000.max;
          interval = res10000.interval;
        }
        // console.log(min, max, interval);
        // 不允许出现小数步长（操作3可以不用了）
        if (interval !== null) {
          // 不允许出现小数步长（操作3可以不用了）
          if (interval < 1) {
            interval = 1;
          } else if (interval < 10) {
            // interval = 10;
          } else if (interval < 100) {
            // interval = 100;
          } else if (interval < 1000) {
            interval = 1000;
          }
        }
      }
    }

    if (yData?.length === 1) {
      /**
       * 操作2: 处理数最大值和最小值相等，一条横线的情况（一般情况下此时的数量级都很小，一般）
       */
      if (maxValue === minValue) {
        // 最大值翻倍，最小值取0，保证线条在图表中间
        // TODO: 可以支持写死y轴刻度，比如1到5，之后可以放开此限制
        // max = Math.ceil(maxValue * 2);
        // min = 0;
      }
    }

    /**
     * 操作3: 处理即便在y轴格数比较少（比如5）时，步长依旧出现小数的情况
     */
    const step = (maxValue - minValue) / 5;
    if (step < 1) {
      // 由于bug而注释，因为有种情况是最大最小值很大，但是差值很小，导致步长从0一直延伸到最小、最大值，y轴巨长
      // interval = 1;
    } else {
      // 其余情况步长顺其自然，不做处理
      // interval = Math.ceil(step);
    }

    /**
     * 操作4: 处理无数据但仍然要显示都是0的图表的情况
     */
    if (maxValue === 0 && minValue === 0) {
      interval = 1;
    }

    if (min) {
      (ret['yAxis'] as any).min = min;
    }
    if (max) {
      (ret['yAxis'] as any).max = max;
    }
    if (interval) {
      (ret['yAxis'] as any).interval = interval;
    }
  }

  return ret;
};

function getOptions(maxValue: any, minValue: any, length = 0) {
  let min: number | null = null;
  let max: number | null = null;
  let interval: number | null = null;

  const limit = length ? Math.pow(10, length) : 0;
  let zeroStr = '';
  for (let i = 0; i < length; i++) {
    zeroStr += '0';
  }

  if (minValue > limit) {
    min = length ? Number(Math.floor(minValue / limit) + zeroStr) : minValue;
  }
  if (maxValue > limit) {
    max = length ? Number(Math.ceil(maxValue / limit) + zeroStr) : maxValue;
  }
  if (minValue > limit || maxValue > limit) {
    min = minValue > 100 ? min : minValue;
    max = maxValue > 100 ? max : maxValue;
    interval = ((max as number) - (min as number)) / 5;
  }

  return { max, min, interval };
}
